whalibmob 5.5.67 → 5.5.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli.js CHANGED
@@ -90,7 +90,19 @@ function enableWireTrace() {
90
90
  // reformat its lines on the way out. Anything that is not a pino record is
91
91
  // passed through byte-for-byte.
92
92
  const stamp = () => new Date().toISOString().slice(11, 23);
93
- const trace = (s) => _origStderrWrite(s + '\n');
93
+ // Traffic arrives while readline owns the bottom line, so writing straight
94
+ // out overwrites the prompt and leaves the two interleaved. Clear the line
95
+ // first and redraw the prompt after, the same way the CLI's own event
96
+ // handlers do.
97
+ const trace = (s) => {
98
+ const live = _rl && process.stdout.isTTY;
99
+ if (live) {
100
+ readline.cursorTo(process.stdout, 0);
101
+ readline.clearLine(process.stdout, 0);
102
+ }
103
+ _origStderrWrite(s + '\n');
104
+ if (live) _rl.prompt(true);
105
+ };
94
106
 
95
107
  // Route the library's internal [DBG] stream through pino at full verbosity.
96
108
  // pino writes newline-delimited JSON straight to fd 1 via sonic-boom, which
@@ -162,6 +174,47 @@ function enableWireTrace() {
162
174
  }
163
175
  }
164
176
 
177
+ // The Noise handshake never goes through sendNode — sendNode refuses to run
178
+ // until the channel is secured, and the ClientHello/ClientFinish frames are
179
+ // written straight to the TCP socket. Wrap that socket as soon as connect()
180
+ // creates it so the handshake is visible too, then step aside once the
181
+ // channel is up and the stanza-level hooks take over.
182
+ const HS_OUT = ['ClientHello', 'ClientFinish'];
183
+ const HS_IN = ['ServerHello'];
184
+ const origConnect = NoiseSocket.prototype.connect;
185
+ NoiseSocket.prototype.connect = function (...args) {
186
+ const result = origConnect.apply(this, args);
187
+ const sock = this.socket;
188
+ if (sock && !sock.__waTraced) {
189
+ sock.__waTraced = true;
190
+ let outN = 0, inN = 0;
191
+ trace(`\n${C.out}${stamp()} ──▶ TCP CONNECT ${sock.remoteAddress || ''}${C.off}`);
192
+
193
+ const origWrite = sock.write.bind(sock);
194
+ sock.write = (chunk, ...rest) => {
195
+ if (!this.secured && Buffer.isBuffer(chunk)) {
196
+ const name = HS_OUT[outN++] || 'handshake frame';
197
+ trace(`\n${C.out}${stamp()} ──▶ NOISE ${name} (${chunk.length} bytes)${C.off}`);
198
+ trace(` ${C.dim}${chunk.toString('hex')}${C.off}`);
199
+ }
200
+ return origWrite(chunk, ...rest);
201
+ };
202
+
203
+ sock.on('data', (d) => {
204
+ if (this.secured) return;
205
+ // Label positionally, but say so when the reply is plainly not a Noise
206
+ // frame — a proxy or captive portal answering in ASCII is worth reading
207
+ // as text rather than staring at its hex.
208
+ const ascii = isPrintable(d);
209
+ const name = ascii ? 'unexpected plaintext reply' : (HS_IN[inN++] || 'handshake frame');
210
+ trace(`\n${C.in}${stamp()} ◀── NOISE ${name} (${d.length} bytes)${C.off}`);
211
+ trace(` ${C.dim}${d.toString('hex').slice(0, 1024)}${C.off}`);
212
+ if (ascii) trace(` ${C.dim}as text: ${JSON.stringify(d.toString('utf8').slice(0, 400))}${C.off}`);
213
+ });
214
+ }
215
+ return result;
216
+ };
217
+
165
218
  const origSendNode = NoiseSocket.prototype.sendNode;
166
219
  NoiseSocket.prototype.sendNode = function (node) {
167
220
  try { logStanza('OUT', node); } catch (_) {}
@@ -158,19 +158,27 @@ async function iosAppAttest(noisePubB64) {
158
158
  // ENC envelope, so the Play Integrity nonce is derived from the store (a stable
159
159
  // per-session value), NOT from the ENC body. pushToken comes from the optional
160
160
  // push client — empty by default.
161
+ // A field with no value is omitted from the body rather than sent empty.
162
+ // buildForm drops null and keeps '', and the registration server validates the
163
+ // shape of what it receives: an empty push_code is a malformed push_code, and
164
+ // it answers with bad_param/bad_format naming that field. An absent field has
165
+ // nothing to validate, which is what an unattested client should send.
166
+ // Real values are still sent whenever a Frida attestation server supplies them.
167
+ const orNull = (v) => (v === '' || v === undefined ? null : v);
168
+
161
169
  async function attestationFields(device, nonceB64, opts) {
162
170
  opts = opts || {};
163
- const pushToken = opts.pushToken || '';
171
+ const pushToken = orNull(opts.pushToken);
164
172
 
165
173
  if (device && device.os === 'android') {
166
174
  const a = await androidIntegrity(nonceB64 || '');
167
175
  return [
168
- 'gpia', a.gpia,
169
- '_gg', a.gg,
170
- '_gi', a.gi,
171
- '_gp', a.gp,
172
- '_ge', a.ge,
173
- '_ga', a.ga,
176
+ 'gpia', orNull(a.gpia),
177
+ '_gg', orNull(a.gg),
178
+ '_gi', orNull(a.gi),
179
+ '_gp', orNull(a.gp),
180
+ '_ge', orNull(a.ge),
181
+ '_ga', orNull(a.ga),
174
182
  'push_token', pushToken
175
183
  ];
176
184
  }
@@ -424,7 +424,9 @@ function getRequestVerificationCodeParameters(store, method, meta, device, attem
424
424
  'manage_call_permission', 'false',
425
425
  'clicked_education_link', 'false',
426
426
  'aid', '',
427
- 'push_code', ''
427
+ // Omitted unless a push client supplies a real code — an empty value is
428
+ // rejected as bad_format, an absent field is not validated at all.
429
+ 'push_code', null
428
430
  ];
429
431
  }
430
432
 
@@ -434,7 +436,8 @@ function getRequestVerificationCodeParameters(store, method, meta, device, attem
434
436
  'sim_mcc', meta.mcc,
435
437
  'sim_mnc', meta.mnc,
436
438
  'jailbroken', '0',
437
- 'push_code', '',
439
+ // Omitted unless a push client supplies a real code (see above).
440
+ 'push_code', null,
438
441
  'cellular_strength', '1'
439
442
  ];
440
443
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whalibmob",
3
- "version": "5.5.67",
3
+ "version": "5.5.70",
4
4
  "description": "WhatsApp library for interaction with WhatsApp Mobile API no web",
5
5
  "author": "Kunboruto50",
6
6
  "main": "index.js",