Key Exchange
Let's exchange the flag (securely):
nc crypto.chall.pwnoh.io 13374
分析给出的代码,发现当输入的B等于g的时候,A的值即为shared_secret
,从而可以得到AES密钥,解密后即可得到flag.
使用nc连接服务器:
╭─ ~/CTF/BuckeyeCTF2021
╰─$ nc crypto.chall.pwnoh.io 13374
I'm going to send you the flag.
However, I noticed that an FBI agent has been eavesdropping on my messages,
so I'm going to send it to you in a way that ONLY YOU can decrypt the flag.
p = 10880518517873967643757501014080864657695946662967756945469976115601889926901188881654458659008874387964581741306546485865737476973040012870453076020399351
g = 5
A = 6446823763385202977767001480185601116794559100492085785295943164615816598597259338015414246293095497644717507604784350316218874347470456507125850300019180
Give me your public key B: 5
ciphertext = a54eef574e0764239040ee22ffe762c907e7390372bf7de1f8ea7db0fa8218490890d545e5694332c8de1154fdff4cfb830a304df635217155b453bd12beb4e8
代码
def decrypt():
shared_secret = 6446823763385202977767001480185601116794559100492085785295943164615816598597259338015414246293095497644717507604784350316218874347470456507125850300019180
key = hashlib.sha1(cun.long_to_bytes(shared_secret)).digest()[:16]
cipher = AES.new(key, AES.MODE_ECB)
message = 0xa54eef574e0764239040ee22ffe762c907e7390372bf7de1f8ea7db0fa8218490890d545e5694332c8de1154fdff4cfb830a304df635217155b453bd12beb4e8
plaintext = cipher.decrypt(cun.long_to_bytes(message))
print(plaintext)
decrypt()
flag:buckeye{DH_1s_s0_h3ck1ng_c00l_l1k3_wh0_w0uldv3_th0ught_0f_th1s?}
layers
Check out my brand new docker repo https://hub.docker.com/r/qxxxb/layers
查看镜像历史,发现曾经存在一个flag.png
,但是被删除了
[root@VM-8-4-centos ~] docker history qxxxb/layers
IMAGE CREATED CREATED BY SIZE COMMENT
0c01a25ae5b7 5 days ago /bin/sh -c echo "Sorry, the flag has been de… 36B
<missing> 5 days ago /bin/sh -c rm flag.png 0B
<missing> 5 days ago /bin/sh -c #(nop) COPY multi:6b3bd56201fda03… 599kB
<missing> 8 weeks ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 8 weeks ago /bin/sh -c #(nop) ADD file:aad4290d27580cc1a… 5.6MB
使用docker save
将镜像保存成tar包并解压,然后再解压每一层文件夹中中的layer.tar
找到flag.png
[root@VM-8-4-centos ~] docker save qxxxb/layers -o a.tar
[root@VM-8-4-centos ~]# tar xvf a.tar
0c01a25ae5b745b06c68c7b870b848f327227e06feca8f121c105d3cc423ebc9.json
7c029681dc775f74b57cccd272523fd31a20f89cc2db9b514981fcbfb467b5c8/
7c029681dc775f74b57cccd272523fd31a20f89cc2db9b514981fcbfb467b5c8/VERSION
7c029681dc775f74b57cccd272523fd31a20f89cc2db9b514981fcbfb467b5c8/json
7c029681dc775f74b57cccd272523fd31a20f89cc2db9b514981fcbfb467b5c8/layer.tar
8771987229b6efdf7a40855b92529d9287e96ead2f6668d84f6a07809818db52/
8771987229b6efdf7a40855b92529d9287e96ead2f6668d84f6a07809818db52/VERSION
8771987229b6efdf7a40855b92529d9287e96ead2f6668d84f6a07809818db52/json
8771987229b6efdf7a40855b92529d9287e96ead2f6668d84f6a07809818db52/layer.tar
c37364b4cf72fc0eb131ee6d62795ef9cf3641340dd0aa8da6849b4c9cd5c41f/
c37364b4cf72fc0eb131ee6d62795ef9cf3641340dd0aa8da6849b4c9cd5c41f/VERSION
c37364b4cf72fc0eb131ee6d62795ef9cf3641340dd0aa8da6849b4c9cd5c41f/json
c37364b4cf72fc0eb131ee6d62795ef9cf3641340dd0aa8da6849b4c9cd5c41f/layer.tar
c6dd22d66071385f6a0d7242a2f2a895073c8ab84871b56390a3449038a49727/
c6dd22d66071385f6a0d7242a2f2a895073c8ab84871b56390a3449038a49727/VERSION
c6dd22d66071385f6a0d7242a2f2a895073c8ab84871b56390a3449038a49727/json
c6dd22d66071385f6a0d7242a2f2a895073c8ab84871b56390a3449038a49727/layer.tar
manifest.json
repositories
[root@VM-8-4-centos ~]# tar xvf 7c029681dc775f74b57cccd272523fd31a20f89cc2db9b514981fcbfb467b5c8/layer.tar
Dockerfile
flag.png
flag:buckeye{D0CK3R_H4S_L4Y3RS}
replay
Somebody pwned my app! Luckily I managed to capture the network traffic of their exploit. Oh by the way, the same app is also running on misc.chall.pwnoh.io
on port 13371
. Can you pwn it for me?
使用Wireshark分析replay.pcap
文件,跟踪TCP流,发现似乎是发送了一些数据拿到Shell权限后,执行了一些命令.
对着“Data”右键,选择“导出分组字节流”,保存字节流数据至a.bin
编写脚本,使用pwn连接服务器并发送数据,执行shell命令,找到flag.txt
文件
╭─ ~/CTF/BuckeyeCTF2021
╰─$ python a.py
[+] Opening connection to misc.chall.pwnoh.io on port 13371: Done
[*] Switching to interactive mode
$ ls
chall
flag.txt
$ cat flag.txt
buckeye{g00d_th1ng_P1E_w4s_d1s4bl3d_0n_th3_b1n4ry}
代码:
from pwn import *
p = remote('misc.chall.pwnoh.io', 13371)
p.recvuntil(b'TODAY', drop=True)
p.recvline()
with open('a.bin','rb') as f:
data = f.read()
p.send(data)
p.interactive()
p.close()
flag:buckeye{g00d_th1ng_P1E_w4s_d1s4bl3d_0n_th3_b1n4ry}
Buttons
Anyone taken Software 1? Can you help me figure out what this weird Java program does?
用javadecompilers反编译Buttons.jar
得到源码.
观察到有一个printFlag
函数,但是依赖于moveHistory
,所以不能通过直接运行printFlag
来得到flag.
分析调用printFlag
函数的actionPerformed
,发现:只有当前点击的方格是isLegalMove
的时候,才会被加到moveHistory
里;当前点击的方格是最后一个时就会打印出flag
.
继续分析isLegalMove
函数,发现该函数返回为True
时必须满足grid[n][n2] == 0
.
那么我们可以在初始化的时候,将所有满足grid[n][n2] == 0
的方格设为🏁,然后依次点击显示为🏁的方格即可.
this.buttons[i][j] = new JButton("?");
if(this.grid[i][j] == 0){
this.buttons[i][j].setText("\u2691");
}
使用javac
命令将源代码编译为Java字节码文件并运行.
╭─ ~/CTF/BuckeyeCTF2021
╰─$ javac Buttons.java
注: Buttons.java使用了未经检查或不安全的操作。
注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
╭─ ~/CTF/BuckeyeCTF2021
╰─$ java Buttons
代码
/*
* Decompiled with CFR 0.150.
*/
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public final class Buttons
extends JFrame
implements ActionListener {
private static final int[][] grid = new int[][]{
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1},
{1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}
};
private final int rows;
private final int cols;
private final JLabel movesLabel;
private final JButton resetButton;
private final JButton[][] buttons;
private int posRow;
private int posCol;
private final int endRow;
private final int endCol;
private static final int MAX_MOVES = 139;
private ArrayList<Integer> moveHistory;
public static void main(String[] arrstring) throws Exception {
new Buttons();
}
public Buttons() {
super("Buttons!");
this.resetValues();
this.rows = grid.length;
this.cols = grid[0].length;
this.endRow = this.rows - 1;
this.endCol = this.cols - 2;
JPanel jPanel = new JPanel();
jPanel.setLayout(new BoxLayout(jPanel, 3));
JPanel jPanel2 = new JPanel(new GridLayout(this.rows, this.cols));
JPanel jPanel3 = new JPanel();
this.buttons = new JButton[this.rows][this.cols];
for (int i = 0; i < this.rows; ++i) {
for (int j = 0; j < this.cols; ++j) {
this.buttons[i][j] = new JButton("?");
if(this.grid[i][j] == 0) {
this.buttons[i][j].setText("\u2691");
}
this.buttons[i][j].addActionListener(this);
this.buttons[i][j].setActionCommand(Integer.toString(j + i * this.cols));
jPanel2.add(this.buttons[i][j]);
}
}
this.buttons[this.endRow][this.endCol].setText("\u2691");
jPanel2.setPreferredSize(new Dimension(45 * this.rows, 45 * this.cols));
this.movesLabel = new JLabel("Moves left: 20");
jPanel3.add(this.movesLabel);
this.resetButton = new JButton("Reset");
this.resetButton.addActionListener(this);
this.resetButton.setActionCommand("reset");
jPanel3.add(this.resetButton);
jPanel.add(jPanel2);
jPanel.add(jPanel3);
this.resetGUI();
this.getContentPane().add(jPanel);
this.pack();
this.setDefaultCloseOperation(3);
this.setVisible(true);
}
private void resetValues() {
this.posRow = 0;
this.posCol = 1;
this.moveHistory = new ArrayList();
this.moveHistory.add(this.posCol + this.posRow * this.cols);
}
private void updateMovesLeft() {
this.movesLabel.setText("Moves left: " + Integer.toString(139 - this.moveHistory.size()));
}
private void resetGUI() {
for (int i = 0; i < this.rows; ++i) {
for (int j = 0; j < this.cols; ++j) {
this.buttons[i][j].setEnabled(true);
}
}
for (int j : this.moveHistory) {
int n = j / this.cols;
int n2 = j % this.cols;
this.buttons[n][n2].setEnabled(false);
}
this.updateMovesLeft();
}
private void reset() {
this.resetValues();
this.resetGUI();
}
private boolean isLegalMove(int n, int n2) {
if (139 - this.moveHistory.size() <= 0) {
return false;
}
return grid[n][n2] == 0 && Math.abs(n - this.posRow) + Math.abs(n2 - this.posCol) == 1;
}
private void printFlag() {
BigInteger bigInteger;
BigInteger[] arrbigInteger = new BigInteger[this.moveHistory.size()];
arrbigInteger[0] = BigInteger.valueOf(2L);
for (int i = 1; i < arrbigInteger.length; ++i) {
arrbigInteger[i] = arrbigInteger[i - 1].nextProbablePrime();
}
BigInteger bigInteger2 = BigInteger.valueOf(1L);
BigInteger bigInteger3 = new BigInteger("1430313837704837266267655033918654049072573502772041995300810633148485540425442305963378206448908414865491202671058946396326575688430628383447817933039379");
for (int i = 0; i < this.moveHistory.size(); ++i) {
bigInteger = BigInteger.valueOf(this.moveHistory.get(i).intValue());
bigInteger2 = bigInteger2.multiply(arrbigInteger[i].modPow(bigInteger, bigInteger3)).mod(bigInteger3);
}
BigInteger bigInteger4 = new BigInteger("1181624346478884506978387685027501257422054115549381320819711748725513305918055802813085700551988448885328987653245675378090761255233757606571908411691314");
bigInteger = bigInteger4.multiply(bigInteger2).mod(bigInteger3);
byte[] arrby = bigInteger.toByteArray();
String string = new String(arrby, StandardCharsets.UTF_8);
JOptionPane.showMessageDialog(this, "Congrats! The flag is: " + string, "Flag", 1);
System.out.println(string);
}
@Override
public void actionPerformed(ActionEvent actionEvent) {
String string = actionEvent.getActionCommand();
if (string.equals("reset")) {
this.reset();
} else {
int n;
int n2 = Integer.parseInt(string);
int n3 = n2 / this.cols;
if (this.isLegalMove(n3, n = n2 % this.cols)) {
this.buttons[n3][n].setEnabled(false);
this.posRow = n3;
this.posCol = n;
this.moveHistory.add(n2);
System.out.println(this.moveHistory);
this.updateMovesLeft();
if (this.posRow == this.endRow && this.posCol == this.endCol) {
this.printFlag();
}
} else {
JOptionPane.showMessageDialog(this, "Illegal move, you lose \u2639", "Illegal move", 0);
this.reset();
}
}
}
}
flag:buckeye{am4z1ng_j0b_y0u_b1g_j4va_h4ck3r}
pay2win
Kyle started an online magazine (The Daily Kyle) and published one of my articles on his site. Don't worry, the article literally contains the flag in plaintext, but if you want to read it you'll have to figure out how to bypass the paywall.
URL: https://pay2win.chall.pwnoh.io
查看网页源代码,发现plantFlag
函数,粘贴到Console中运行后,打印出shwl_l1_twcd14}1ry4ht3neck_t3_bs{1c_hkh_tsh3he03gy_3l_hu
.
const ciphertext = [
234, 240, 234, 252, 214, 236, 140, 247, 173, 191, 158, 132, 56, 4, 32, 73, 235, 193, 233, 152,
125, 19, 19, 237, 186, 131, 98, 52, 186, 143, 127, 43, 226, 233, 126, 15, 225, 171, 85, 55,
173, 123, 21, 147, 97, 21, 237, 11, 254, 129, 2, 131, 101, 63, 149, 61,
];
const plaintext = ciphertext.map((x, i) => (i * i) % 256 ^ x ^ 0x99);
const flagElement = document.querySelector("#flag");
plaintext.map((x, i) => {
const span = document.createElement("span");
span.classList.add(`flag-char-${i}`);
span.textContent = String.fromCharCode(x);
flagElement.appendChild(span);
return span;
});
查看main.css
,发现span
都被设置了order
属性.
我们可以把main.css
,main.js
和网页源代码a.html
下载到本地.然后注释掉main.js
里弹窗和阻止滚动的代码.
打开a.html
,发现本应该显示flag
的地方有一个灰色的框.
编辑a.html
,将 <code id="flag"></code>
这一行代码移动至<pre>
标签外面,即可看到flag
.
flag:buckeye{h0ly_sh1t_wh4t_th3_h3ck_1s_th1s_w31rd_ch4ll3ng3}